#include "Juego.h"
#include "Mover.h"
#include <stdio.h>

enum {ASIGNACION, REFUERZO, ATAQUE, FORTIFICACION, FINAL};
enum {MSG_ASIGNAR, MSG_REFORZAR, MSG_ERR_NOVECINOS, MSG_SEL_ATACANTE, MSG_SEL_DEFENSOR, 
MSG_SEL_ORIGEN, MSG_SEL_DESTINO, MSG_FORTIFICAR, MSG_ERR_NOEJ, MSG_ERR_NOPROP, MSG_VICTORIA};

Juego::Juego(QWidget *parent, int nJug, QString nombres[6], QColor colores[6], QWidget *mwin) 
: MyWidget(parent){
    setupUi();
    mainwin=mwin;
    inicializarAtaque();
    
    turno=0;
    nCanjes=0;
    conquista=false;
    fase=ASIGNACION; 
    nJugadores=nJug; 
    
    int nInicial;    
    switch(nJugadores){
        case 2: nInicial=40; break;
        case 3: nInicial=35; break;
        case 4: nInicial=30; break;
        case 5: nInicial=25; break;
        case 6: nInicial=20;
    }
    
    for(int i=0; i < nJugadores; i++)
        jugadores[i].inicializar(nInicial,nombres[i],colores[i]);
    for(int i=0; i < 42; i++)
        territorios[i].inicializar(i);
    
    connect(mapa, SIGNAL(mouseReleased(int)), this, SLOT(clickTerritorio(int)));
    connect(btnAtaque, SIGNAL(clicked()), this, SLOT(clickAccion()));
    connect(btnCartas, SIGNAL(clicked()), this, SLOT(clickCartas()));
    actualizarInfo(MSG_ASIGNAR);
    //btnCartas->setEnabled(false);
    
}

void Juego::clickTerritorio(int nTerritorio){
    if (nTerritorio > 42) return;
    
    switch(fase){
        case ASIGNACION:            
            if (territorios[nTerritorio].asignar(turno, &jugadores[0])){ 
                mapa->asignarIndicador(nTerritorio, jugadores[turno].color, 
                    territorios[nTerritorio].nEjercitos);
                if (validarAsignacion()){
                    fase=REFUERZO;
                    //btnCartas->setEnabled(true);
                }
                cambiarTurno();
            }
            break;
        case REFUERZO:
            if (territorios[nTerritorio].ocupar(turno, &jugadores[0])){ 
                mapa->actualizarIndicador(nTerritorio, territorios[nTerritorio].nEjercitos);
                actualizarInfo(MSG_REFORZAR);
                if (validarRefuerzo()) {
                    fase=ATAQUE;
                    actualizarInfo(MSG_SEL_ATACANTE);
                    //btnCartas->setEnabled(false);
                    btnAtaque->setEnabled(true);
                }
            }
            break;
        case ATAQUE:
            if(!seleccionado)
                if(territorios[nTerritorio].nJugador==turno)
                    if(territorios[nTerritorio].nEjercitos > 1){
                        seleccionado=true;
                        nAtacante=nTerritorio;
                        printf("Atacante: %i\n", nAtacante);
                        actualizarInfo(MSG_SEL_DEFENSOR);
                    }else{
                        actualizarInfo(MSG_ERR_NOEJ);
                        printf("El territorio %i debe tener mas de 1 ejercito\n", nTerritorio);
                    }
                else{
                    actualizarInfo(MSG_ERR_NOPROP);
                    printf("El territorio %i no le pertenece\n", nTerritorio);
                }
            else
                if(territorios[nTerritorio].nJugador==turno)
                    if(territorios[nTerritorio].nEjercitos > 1){
                        nAtacante=nTerritorio;
                        printf("Cambio de Atacante: %i\n", nAtacante);
                        actualizarInfo(MSG_SEL_DEFENSOR);
                    }else{
                        actualizarInfo(MSG_ERR_NOEJ);
                        printf("El territorio %i debe tener mas de 1 ejercito\n", nTerritorio);
                    }
                else
                    if(territorios[nTerritorio].esVecino(nAtacante)){
                        printf("Defensor: %i, PLOMO!\n", nTerritorio);
                        int defJug = territorios[nTerritorio].nJugador;
                        frmAtacar = new Atacar(0,territorios,nAtacante,nTerritorio);
                        frmAtacar->exec();
                        
                        if(territorios[nTerritorio].nJugador==turno)
                            conquista=true;
                        
                        eliminarJugador(defJug);
                        if(validarVictoria(turno)){
                            btnAtaque->setText("Salir");
                            btnCartas->setEnabled(false);
                            actualizarInfo(MSG_VICTORIA);
                            fase=FINAL;
                            QMessageBox::information(this, QString("Victoria!"),
                                jugadores[turno].nombre+QString(" ha ganado la partida"),
                                QMessageBox::AcceptRole);
                        }else
                            actualizarInfo(MSG_SEL_ATACANTE);
                        
                        mapa->actualizarIndicador(nAtacante,territorios[nAtacante].nEjercitos);
                        mapa->asignarIndicador(nTerritorio,territorios[nTerritorio].color,
                            territorios[nTerritorio].nEjercitos);
                        
                        inicializarAtaque();                        
                    }else{
                        actualizarInfo(MSG_ERR_NOVECINOS);
                        printf("El territorio %i no es vecino de %i\n", nAtacante, nTerritorio);
                    }
            break;
        case FORTIFICACION:
            if(!seleccionado)
                if(territorios[nTerritorio].nJugador==turno)
                    if(territorios[nTerritorio].nEjercitos > 1){
                        seleccionado=true;
                        nAtacante=nTerritorio;
                        actualizarInfo(MSG_SEL_DESTINO);
                    }else{
                        actualizarInfo(MSG_ERR_NOEJ);
                        printf("El territorio origen debe tener mas de 1 ejercito\n");
                    }
                else{
                    actualizarInfo(MSG_ERR_NOPROP);
                    printf("Debe seleccionar un territorio en su poder\n");
                }
            else
                if(territorios[nTerritorio].nJugador==turno)
                    if(territorios[nTerritorio].esVecino(nAtacante)){
                        frmMover = new Mover(0,territorios,nAtacante,nTerritorio,1);
                        frmMover->exec();
                        mapa->actualizarIndicador(nAtacante,territorios[nAtacante].nEjercitos);
                        mapa->actualizarIndicador(nTerritorio,territorios[nTerritorio].nEjercitos);
                        fase=REFUERZO;
                        btnAtaque->setText("Finalizar Ataque");
                        btnAtaque->setEnabled(false);
                        cambiarTurno();
                    }else{
                        actualizarInfo(MSG_ERR_NOVECINOS);
                        printf("Debe seleccionar un territorio vecino\n");
                    }
                else{
                    actualizarInfo(MSG_ERR_NOPROP);
                    printf("Debe seleccionar un territorio en su poder\n");
                }
            break;
    }
}

void Juego::inicializarAtaque(){
    seleccionado=false;
    nAtacante=-1;
}

void Juego::clickAccion(){
    if (fase==ATAQUE){
        if ((conquista) && (jugadores[turno].nCartas < 5)){
            jugadores[turno].recibirCarta(mazo.obtenerCarta());
            conquista=false;
        }
        fase=FORTIFICACION;
        btnAtaque->setText("Finalizar Fortificacion");
        btnAtaque->setEnabled(true);
        actualizarInfo(MSG_FORTIFICAR);
    }else if (fase==FORTIFICACION){
        fase=REFUERZO;
        btnAtaque->setText("Finalizar Ataque");
        btnAtaque->setEnabled(false);
        cambiarTurno();
    }else if (fase==FINAL){
        database = Database();
        if (!database.conectar()){
            QMessageBox *aviso = new QMessageBox(QMessageBox::Warning, 
                "Error de base de datos", 
                "No se ha podido conectar a la base de datos", 
                QMessageBox::Ok, this);
            aviso->exec();
        }else{
            int tropas=0;
            for (int i=0; i < 42; i++){
                if (territorios[i].nJugador == turno)
                    tropas += territorios[i].nEjercitos;
            }
            database.insertar(jugadores[turno].nombre, tropas);
            database.desconectar();
        }
        mainwin->show();
        close();
    }
}

void Juego::clickCartas(){
    Cartas *frmCartas = new Cartas(0,&mazo,&jugadores[turno],turno,territorios,&nCanjes);
    frmCartas->exec();
    //Redibujar indicadores del jugador
    for(int i=0;i<42;i++)
        if(territorios[i].nJugador==turno)
            mapa->actualizarIndicador(i,territorios[i].nEjercitos);            
    actualizarInfo(MSG_REFORZAR);
}
bool Juego::validarAsignacion(){
    bool cambiar=true;
    for (int i=0; i < nJugadores; i++)
        if (jugadores[i].nEjercitos > 0) {cambiar=false; break;}
    return cambiar;
}

bool Juego::validarRefuerzo(){
    if (jugadores[turno].nEjercitos > 0) return false;
    return true;
}

bool Juego::validarAtaque(){
    return true;
}

bool Juego::validarFortificacion(){
    return true;
}

void Juego::cambiarTurno(){
    jugadores[turno].asigno=false;
    
    do{
        if(turno > nJugadores)
            turno=0;
        else
            turno++;
    }while(!jugadores[turno].jugando);
    printf ("Nuevo turno: %i\n", turno);
    
    if (fase==REFUERZO){
        jugadores[turno].nEjercitos = calcularRefuerzos();
        actualizarInfo(MSG_REFORZAR);
    }else
        actualizarInfo(MSG_ASIGNAR);
}

bool Juego::validarVictoria(int nJug){
    for(int i=0; i < nJugadores; i++)
        if ((i!=nJug) && (jugadores[i].jugando)) return false;
    return true;
}

void Juego::eliminarJugador(int nJug){
    for(int i=0; i < 42; i++)
        if(territorios[i].nJugador==nJug) return;
    
    jugadores[nJug].jugando=false;
    printf ("Eliminado jugador %i\n",nJug);
}

int Juego::calcularRefuerzos(){
    int ocupados=0, refuerzos=0;
    //Territorios ocupados
    for (int i=0; i < 42; i++)
        if (territorios[i].nJugador==turno) ocupados++;
    
    if (ocupados <= 11)
        refuerzos = 3;
    else
        refuerzos += (ocupados)/3;
    
    //Continentes dominados
    bool domina;
    for (int i=0; i < 6; i++){
        domina=true;
        for (int j=0; j < 12; j++){
            if (continentes[i][j]==-1) continue;
            if (territorios[continentes[i][j]].nJugador!=turno) domina=false;
        }
        if (domina==true) refuerzos += refuerzosContinente[i];
    }
    
    printf ("Refuerzos: %i\n", refuerzos);
    return refuerzos;
}

void Juego::actualizarInfo(int type){
    QPalette p = palette();
    p.setColor(QPalette::Window, jugadores[turno].color);
    lblInfo->setPalette(p);
    
    QString cad="", num;
    cad.append(jugadores[turno].nombre);
    
    switch(fase){
        case ASIGNACION:
            cad.append(" - Fase de asignacion - ");
            break;
        case REFUERZO:
            cad.append(" - Fase de refuerzos - ");
            break;
        case ATAQUE:
            cad.append(" - Fase de ataque - ");
            break;
        case FORTIFICACION:
            cad.append(" - Fase de fortificacion - ");
    }
    switch(type){
        case MSG_ASIGNAR:
            num.setNum(jugadores[turno].nEjercitos);
            cad.append("Asigna un ejercito en un territorio libre. ");
            cad.append(num);
            cad.append(" ejercitos restantes");
            break;
        case MSG_REFORZAR:
            num.setNum(jugadores[turno].nEjercitos);
            cad.append("Refuerza tus territorios. ");
            cad.append(num);
            cad.append(" ejercitos restantes");
            break;
        case MSG_ERR_NOVECINOS:
            cad.append("Solo puedes seleccionar paises vecinos");
            break;
        case MSG_SEL_ATACANTE:
            cad.append("Seleccione al territorio atacante");
            break;
        case MSG_SEL_DEFENSOR:
            cad.append(territorios[nAtacante].nombre);
            cad.append(" es el atacante. Ahora seleccione al territorio defensor");
            break;
        case MSG_SEL_ORIGEN:
            cad.append("Seleccione al territorio origen");
            break;
        case MSG_SEL_DESTINO:
            cad.append(territorios[nAtacante].nombre);
            cad.append(" es el origen. Ahora seleccione al territorio destino");
            break;
        case MSG_FORTIFICAR:
            cad.append("Fortifique sus territorios");
            break;
        case MSG_ERR_NOEJ:
            cad.append("Debe seleccionar un territorio con mas de 1 ejercito");
            break;
        case MSG_ERR_NOPROP:
            cad.append("Debe seleccionar un territorio en su poder");
            break;
        case MSG_VICTORIA:
            cad = "";
            cad.append(jugadores[turno].nombre);
            cad.append(" ha conquistado el mundo! VICTORIA");
            break;
        
            
    }
    
    lblInfo->setText(cad);
}

void Juego::setupUi(){
    resize(825, 520); 
    setWindowTitle("Risk");
    lblInfo = new QLabel(this);
    lblInfo->setText("Informacion de la partida");
    lblInfo->setGeometry(QRect(10, 10, 805, 26));
    lblInfo->setFrameShape(QFrame::Box);
    lblInfo->setAutoFillBackground(true);
    btnAtaque = new QPushButton(this);
    btnAtaque->setText("Finalizar ataque");
    btnAtaque->setGeometry(QRect(676, 470, 141, 36));
    btnAtaque->setEnabled(false);
    btnCartas = new QPushButton(this);
    btnCartas->setText("Cartas");
    btnCartas->setGeometry(QRect(520, 470, 141, 36));
    
    mapa = new GView(this);
    mapa->setGeometry(QRect(10,45,805,415));
}
